

<!doctype html>

<html lang="en" data-content_root="../../">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>skidl.part &#8212; SKiDL 2.2.0 documentation</title>
    <link rel="stylesheet" type="text/css" href="../../_static/pygments.css?v=fa44fd50" />
    <link rel="stylesheet" type="text/css" href="../../_static/bizstyle.css?v=a66e137f" />
    
    <script src="../../_static/documentation_options.js?v=b21de401"></script>
    <script src="../../_static/doctools.js?v=9bcbadda"></script>
    <script src="../../_static/sphinx_highlight.js?v=dc90522c"></script>
    <script src="../../_static/bizstyle.js"></script>
    <link rel="index" title="Index" href="../../genindex.html" />
    <link rel="search" title="Search" href="../../search.html" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <!--[if lt IE 9]>
    <script src="_static/css3-mediaqueries.js"></script>
    <![endif]-->
  </head><body>
    <h1 id="site-title"><a href="../../../../"><img src="../../../../images/slim_banner.png" width="100%"></a></h1>
    
    <div class="related" role="navigation" aria-label="Related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="nav-item nav-item-0"><a href="../../index.html">SKiDL 2.2.0 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../index.html" accesskey="U">Module code</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">skidl.part</a></li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <h1>Source code for skidl.part</h1><div class="highlight"><pre>
<span></span><span class="c1"># -*- coding: utf-8 -*-</span>

<span class="c1"># The MIT License (MIT) - Copyright (c) Dave Vandenbout.</span>

<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Handles parts in a circuit.</span>

<span class="sd">This module provides classes and functions for creating, managing, and connecting electronic parts</span>
<span class="sd">in a circuit. Parts can be instantiated from libraries, customized with attributes, and connected</span>
<span class="sd">to form complete circuits.</span>
<span class="sd">&quot;&quot;&quot;</span>

<span class="kn">import</span> <span class="nn">functools</span>
<span class="kn">from</span> <span class="nn">collections.abc</span> <span class="kn">import</span> <span class="n">Iterable</span>
<span class="kn">from</span> <span class="nn">copy</span> <span class="kn">import</span> <span class="n">copy</span>
<span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>

<span class="kn">from</span> <span class="nn">.design_class</span> <span class="kn">import</span> <span class="n">PartClass</span><span class="p">,</span> <span class="n">PartClasses</span>
<span class="kn">from</span> <span class="nn">.erc</span> <span class="kn">import</span> <span class="n">dflt_part_erc</span>
<span class="kn">from</span> <span class="nn">.logger</span> <span class="kn">import</span> <span class="n">active_logger</span>
<span class="kn">from</span> <span class="nn">.mixins</span> <span class="kn">import</span> <span class="n">PinMixin</span>
<span class="kn">from</span> <span class="nn">.node</span> <span class="kn">import</span> <span class="n">HIER_SEP</span>
<span class="kn">from</span> <span class="nn">.skidlbaseobj</span> <span class="kn">import</span> <span class="n">SkidlBaseObject</span>
<span class="kn">from</span> <span class="nn">.utilities</span> <span class="kn">import</span> <span class="p">(</span>
    <span class="n">add_unique_attr</span><span class="p">,</span>
    <span class="n">export_to_all</span><span class="p">,</span>
    <span class="n">filter_list</span><span class="p">,</span>
    <span class="n">find_num_copies</span><span class="p">,</span>
    <span class="n">get_unique_name</span><span class="p">,</span>
    <span class="n">rmv_unique_name</span><span class="p">,</span>
    <span class="n">list_or_scalar</span><span class="p">,</span>
    <span class="n">to_list</span><span class="p">,</span>
    <span class="n">Rgx</span><span class="p">,</span>
<span class="p">)</span>


<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;NETLIST&quot;</span><span class="p">,</span> <span class="s2">&quot;LIBRARY&quot;</span><span class="p">,</span> <span class="s2">&quot;TEMPLATE&quot;</span><span class="p">,</span> <span class="s2">&quot;PartTmplt&quot;</span><span class="p">,</span> <span class="s2">&quot;SkidlPart&quot;</span><span class="p">]</span>


<span class="c1"># Places where parts can be stored.</span>
<span class="c1">#   NETLIST: The part will become part of a circuit netlist.</span>
<span class="c1">#   LIBRARY: The part will be placed in the part list for a library.</span>
<span class="c1">#   TEMPLATE: The part will be used as a template to be copied from.</span>
<span class="n">NETLIST</span><span class="p">,</span> <span class="n">LIBRARY</span><span class="p">,</span> <span class="n">TEMPLATE</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;NETLIST&quot;</span><span class="p">,</span> <span class="s2">&quot;LIBRARY&quot;</span><span class="p">,</span> <span class="s2">&quot;TEMPLATE&quot;</span><span class="p">]</span>


<span class="k">class</span> <span class="nc">PinNumberSearch</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A class for restricting part pin indexing to only pin numbers while ignoring pin names.</span>
<span class="sd">    </span>
<span class="sd">    This class enables accessing pins by their number only, even when pins</span>
<span class="sd">    might have both numbers and names.</span>
<span class="sd">    </span>
<span class="sd">    Attributes:</span>
<span class="sd">        part (Part): The part whose pins this object searches through.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">part</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Initialize the pin number search object.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            part (Part): The part whose pins will be searched by number.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c1"># Store the part this object belongs to.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">part</span> <span class="o">=</span> <span class="n">part</span>

    <span class="k">def</span> <span class="nf">get_pins</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">pin_ids</span><span class="p">,</span> <span class="o">**</span><span class="n">criteria</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Get pins from a part using only pin numbers.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            pin_ids: ID numbers of the pins to get from the part.</span>
<span class="sd">            criteria: Additional criteria for selecting pins.</span>
<span class="sd">            </span>
<span class="sd">        Returns:</span>
<span class="sd">            Pin or list: The selected pins.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c1"># Add criteria that restricts pin searching to only numbers.</span>
        <span class="n">criteria</span><span class="p">[</span><span class="s2">&quot;only_search_numbers&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>

        <span class="c1"># Now search the part for pin numbers matching the pin_ids.</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">part</span><span class="o">.</span><span class="n">get_pins</span><span class="p">(</span><span class="o">*</span><span class="n">pin_ids</span><span class="p">,</span> <span class="o">**</span><span class="n">criteria</span><span class="p">)</span>

    <span class="c1"># Get pin numbers from a part using brackets, e.g. [1,5:9].</span>
    <span class="fm">__getitem__</span> <span class="o">=</span> <span class="n">get_pins</span>

    <span class="k">def</span> <span class="fm">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ids</span><span class="p">,</span> <span class="o">*</span><span class="n">pins_nets_buses</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">part</span><span class="o">.</span><span class="fm">__setitem__</span><span class="p">(</span><span class="n">ids</span><span class="p">,</span> <span class="o">*</span><span class="n">pins_nets_buses</span><span class="p">)</span>


<span class="k">class</span> <span class="nc">PinNameSearch</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A class for restricting part pin indexing to only pin names while ignoring pin numbers.</span>
<span class="sd">    </span>
<span class="sd">    This class enables accessing pins by their name only, even when pins</span>
<span class="sd">    might have both numbers and names.</span>
<span class="sd">    </span>
<span class="sd">    Attributes:</span>
<span class="sd">        part (Part): The part whose pins this object searches through.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">part</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Initialize the pin name search object.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            part (Part): The part whose pins will be searched by name.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">part</span> <span class="o">=</span> <span class="n">part</span>

    <span class="k">def</span> <span class="nf">get_pins</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">pin_ids</span><span class="p">,</span> <span class="o">**</span><span class="n">criteria</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Get pins from a part using only pin names.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            pin_ids: Names of the pins to get from the part.</span>
<span class="sd">            criteria: Additional criteria for selecting pins.</span>
<span class="sd">            </span>
<span class="sd">        Returns:</span>
<span class="sd">            Pin or list: The selected pins.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c1"># Add criteria that restricts pin searching to only names.</span>
        <span class="n">criteria</span><span class="p">[</span><span class="s2">&quot;only_search_names&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>

        <span class="c1"># Now search the part for pin names matching the pin_ids.</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">part</span><span class="o">.</span><span class="n">get_pins</span><span class="p">(</span><span class="o">*</span><span class="n">pin_ids</span><span class="p">,</span> <span class="o">**</span><span class="n">criteria</span><span class="p">)</span>

    <span class="c1"># Get pin names from a part using brackets, e.g. [&#39;A1, A2, A3&#39;].</span>
    <span class="fm">__getitem__</span> <span class="o">=</span> <span class="n">get_pins</span>

    <span class="k">def</span> <span class="fm">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ids</span><span class="p">,</span> <span class="o">*</span><span class="n">pins_nets_buses</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">part</span><span class="o">.</span><span class="fm">__setitem__</span><span class="p">(</span><span class="n">ids</span><span class="p">,</span> <span class="o">*</span><span class="n">pins_nets_buses</span><span class="p">)</span>


<div class="viewcode-block" id="Part">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part">[docs]</a>
<span class="nd">@export_to_all</span>
<span class="k">class</span> <span class="nc">Part</span><span class="p">(</span><span class="n">PinMixin</span><span class="p">,</span> <span class="n">SkidlBaseObject</span><span class="p">):</span>
<span class="c1"># class Part(SkidlBaseObject, PinMixin):</span>
<span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A class for storing a definition of a schematic part.</span>
<span class="sd">    </span>
<span class="sd">    This class represents electronic components in a schematic. Parts can be</span>
<span class="sd">    instantiated from libraries, customized with attributes, and connected</span>
<span class="sd">    together to form circuits.</span>

<span class="sd">    Args:</span>
<span class="sd">        lib (str or SchLib, optional): Either a SchLib object or a schematic part library file name.</span>
<span class="sd">        name (str, optional): A string with name of the part to find in the library, or to assign to</span>
<span class="sd">            the part defined by the part definition.</span>
<span class="sd">        dest (str, optional): String that indicates where the part is destined for (e.g., NETLIST).</span>
<span class="sd">        tool (str, optional): The format for the library file or part definition (e.g., KICAD).</span>
<span class="sd">        connections (dict, optional): A dictionary with part pin names/numbers as keys and the</span>
<span class="sd">            nets to which they will be connected as values. For example:</span>
<span class="sd">            { &#39;IN-&#39;:a_in, &#39;IN+&#39;:gnd, &#39;1&#39;:AMPED_OUTPUT, &#39;14&#39;:vcc, &#39;7&#39;:gnd }</span>
<span class="sd">        part_defn (list, optional): A list of strings that define the part (usually read from a</span>
<span class="sd">            schematic library file).</span>
<span class="sd">        circuit (Circuit, optional): The Circuit object this Part belongs to.</span>
<span class="sd">        ref_prefix (str, optional): Prefix for part references such as &#39;U&#39; or &#39;J&#39;.</span>
<span class="sd">        ref (str, optional): A specific part reference to be assigned.</span>
<span class="sd">        tag (str, optional): A specific tag to tie the part to its footprint in the PCB.</span>
<span class="sd">        pin_splitters (str, optional): String of characters that split long pin names into shorter aliases.</span>

<span class="sd">    Keyword Args:</span>
<span class="sd">        kwargs: Name/value pairs for setting attributes for the part.</span>
<span class="sd">            For example, manf_num=&#39;LM4808MP-8&#39; would create an attribute</span>
<span class="sd">            named &#39;manf_num&#39; for the part and assign it the value &#39;LM4808MP-8&#39;.</span>

<span class="sd">    Raises:</span>
<span class="sd">        ValueError: If the part library and definition are both missing.</span>
<span class="sd">        ValueError: If an unknown file format is requested.</span>
<span class="sd">        </span>
<span class="sd">    Attributes:</span>
<span class="sd">        name (str): The part name.</span>
<span class="sd">        description (str): Description of the part.</span>
<span class="sd">        ref (str): Reference designator for the part (e.g., &#39;R1&#39;, &#39;U3&#39;).</span>
<span class="sd">        ref_prefix (str): Prefix for the reference (e.g., &#39;R&#39;, &#39;U&#39;).</span>
<span class="sd">        pins (list): List of Pin objects for this part.</span>
<span class="sd">        unit (dict): Dictionary for storing subunits of the part.</span>
<span class="sd">        circuit (Circuit): The circuit this part belongs to.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c1"># Set the default ERC functions for all Part instances.</span>
    <span class="n">erc_list</span> <span class="o">=</span> <span class="p">[</span><span class="n">dflt_part_erc</span><span class="p">]</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">lib</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">dest</span><span class="o">=</span><span class="n">NETLIST</span><span class="p">,</span>
        <span class="n">tool</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">connections</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">part_defn</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">circuit</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">ref_prefix</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">,</span>
        <span class="n">ref</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">tag</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">pin_splitters</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="o">**</span><span class="n">kwargs</span>
    <span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Initialize a part with the given parameters.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            lib (str or SchLib, optional): Library containing the part.</span>
<span class="sd">            name (str, optional): Part name to search for in the library.</span>
<span class="sd">            dest (str, optional): Destination for the part (NETLIST, LIBRARY, TEMPLATE).</span>
<span class="sd">            tool (str, optional): Tool format (KICAD, SPICE, etc.).</span>
<span class="sd">            connections (dict, optional): Pre-defined connections for the part&#39;s pins.</span>
<span class="sd">            part_defn (list, optional): List of strings defining the part.</span>
<span class="sd">            circuit (Circuit, optional): Circuit the part belongs to.</span>
<span class="sd">            ref_prefix (str, optional): Prefix for the part reference (e.g., &#39;R&#39;, &#39;U&#39;).</span>
<span class="sd">            ref (str, optional): Specific reference designator.</span>
<span class="sd">            tag (str, optional): Tag for associating with PCB footprint.</span>
<span class="sd">            pin_splitters (str, optional): Characters for splitting pin names into aliases.</span>
<span class="sd">            </span>
<span class="sd">        Keyword Args:</span>
<span class="sd">            kwargs: Additional attributes for the part.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="kn">import</span> <span class="nn">skidl</span>
        <span class="kn">from</span> <span class="nn">skidl</span> <span class="kn">import</span> <span class="n">SchLib</span><span class="p">,</span> <span class="n">SKIDL</span>
        <span class="kn">from</span> <span class="nn">skidl.tools.spice</span> <span class="kn">import</span> <span class="n">add_xspice_io</span>

        <span class="c1"># Initialize the base classes. Start with SkidlBaseObject to instantiate basic stuff.</span>
        <span class="c1"># Then do PinMixin to set up handling of pins in the part. Don&#39;t do PinMixin first</span>
        <span class="c1"># because its __getattr__ method will be overridden by __getattr__ in SkidlBaseObject.</span>
        <span class="n">SkidlBaseObject</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="n">PinMixin</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

        <span class="n">tool</span> <span class="o">=</span> <span class="n">tool</span> <span class="ow">or</span> <span class="n">skidl</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">tool</span>

        <span class="c1"># Setup some part attributes that might be overwritten later on.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">do_erc</span> <span class="o">=</span> <span class="kc">True</span>  <span class="c1"># Allow part to be included in ERC.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">unit</span> <span class="o">=</span> <span class="p">{}</span>  <span class="c1"># Dictionary for storing subunits of the part, if desired.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">PinNumberSearch</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>  <span class="c1"># Does pin search using only pin numbers.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">n</span> <span class="o">=</span> <span class="n">PinNameSearch</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>  <span class="c1"># Does pin search using only pin names.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>  <span class="c1"># Assign initial part name.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_ref</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>  <span class="c1"># Provide a member for holding a reference.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tool</span> <span class="o">=</span> <span class="n">tool</span>  <span class="c1"># Initial type of part (SKIDL, KICAD, etc.)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">circuit</span> <span class="o">=</span> <span class="kc">None</span>  <span class="c1"># Part starts off unassociated with any circuit.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_partclasses</span> <span class="o">=</span> <span class="n">PartClasses</span><span class="p">()</span>  <span class="c1"># List of part classes this part belongs to.</span>

        <span class="c1"># Create a Part from a library entry.</span>
        <span class="k">if</span> <span class="n">lib</span><span class="p">:</span>
            <span class="c1"># If the lib argument is a string, then create a library using the</span>
            <span class="c1"># string as the library file name.</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">lib</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
                <span class="n">libname</span> <span class="o">=</span> <span class="n">lib</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="n">lib</span> <span class="o">=</span> <span class="n">SchLib</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="n">libname</span><span class="p">,</span> <span class="n">tool</span><span class="o">=</span><span class="n">tool</span><span class="p">)</span>
                <span class="k">except</span> <span class="ne">FileNotFoundError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
                    <span class="k">if</span> <span class="n">skidl</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">query_backup_lib</span><span class="p">:</span>
                        <span class="n">active_logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
                            <span class="sa">f</span><span class="s1">&#39;Could not load KiCad schematic library &quot;</span><span class="si">{</span><span class="n">libname</span><span class="si">}</span><span class="s1">&quot;, falling back to backup library.&#39;</span>
                        <span class="p">)</span>
                        <span class="n">lib</span> <span class="o">=</span> <span class="n">skidl</span><span class="o">.</span><span class="n">load_backup_lib</span><span class="p">()</span>
                        <span class="k">if</span> <span class="ow">not</span> <span class="n">lib</span><span class="p">:</span>
                            <span class="k">raise</span> <span class="n">e</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="k">raise</span> <span class="n">e</span>

            <span class="c1"># Make a copy of the part from the library but don&#39;t add it to the netlist.</span>
            <span class="n">part</span> <span class="o">=</span> <span class="n">lib</span><span class="p">[</span><span class="n">name</span><span class="p">]</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>

            <span class="c1"># Overwrite self with the new part.</span>
            <span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">part</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">)</span>

            <span class="c1"># Make sure all the pins have a valid reference to this part.</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">associate_pins</span><span class="p">()</span>

            <span class="c1"># Copy part units so all the pin and part references stay valid.</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">copy_units</span><span class="p">(</span><span class="n">part</span><span class="p">)</span>

        <span class="c1"># Otherwise, create a Part from a part definition. If the part is</span>
        <span class="c1"># destined for a library, then just get its name. If it&#39;s going into</span>
        <span class="c1"># a netlist, then parse the entire part definition.</span>
        <span class="k">elif</span> <span class="n">part_defn</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">part_defn</span> <span class="o">=</span> <span class="n">part_defn</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">partial_parse</span><span class="o">=</span><span class="p">(</span><span class="n">dest</span> <span class="o">!=</span> <span class="n">NETLIST</span><span class="p">))</span>

        <span class="c1"># If the part is destined for a SKiDL library, then it will be defined</span>
        <span class="c1"># by the additional attribute values that are passed.</span>
        <span class="k">elif</span> <span class="n">tool</span> <span class="o">==</span> <span class="n">SKIDL</span> <span class="ow">and</span> <span class="n">name</span><span class="p">:</span>
            <span class="k">pass</span>

        <span class="k">else</span><span class="p">:</span>
            <span class="n">active_logger</span><span class="o">.</span><span class="n">raise_</span><span class="p">(</span>
                <span class="ne">ValueError</span><span class="p">,</span>
                <span class="s2">&quot;Can&#39;t make a part without a library &amp; part name or a part definition.&quot;</span><span class="p">,</span>
            <span class="p">)</span>

        <span class="c1"># Split multi-part pin names into individual pin aliases.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">split_pin_names</span><span class="p">(</span><span class="n">pin_splitters</span><span class="p">)</span>

        <span class="c1"># Setup the tag for tieing the part to a footprint in a pcb editor.</span>
        <span class="c1"># Do this before adding the part to the circuit or an exception will occur</span>
        <span class="c1"># because the part can&#39;t give its hierarchical name to the circuit.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tag</span> <span class="o">=</span> <span class="n">tag</span>

        <span class="c1"># Override the reference prefix if it was passed as a parameter.</span>
        <span class="c1"># If nothing was set, default to using &quot;U&quot;.</span>
        <span class="c1"># This MUST be done before adding the part to a circuit below!</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">ref_prefix</span> <span class="o">=</span> <span class="n">ref_prefix</span> <span class="ow">or</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">&quot;ref_prefix&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">)</span> <span class="ow">or</span> <span class="s2">&quot;U&quot;</span>

        <span class="k">if</span> <span class="n">dest</span> <span class="o">!=</span> <span class="n">LIBRARY</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">dest</span> <span class="o">==</span> <span class="n">NETLIST</span><span class="p">:</span>
                <span class="c1"># If the part is going to be an element in a circuit, then add it to the</span>
                <span class="c1"># the circuit and make any indicated pin/net connections.</span>
                <span class="c1"># If no Circuit object is given, then use the default Circuit that always exists.</span>
                <span class="n">circuit</span> <span class="o">=</span> <span class="n">circuit</span> <span class="ow">or</span> <span class="n">default_circuit</span>
                <span class="n">circuit</span> <span class="o">+=</span> <span class="bp">self</span>
            <span class="k">elif</span> <span class="n">dest</span> <span class="o">==</span> <span class="n">TEMPLATE</span><span class="p">:</span>
                <span class="c1"># If this is just a part template, don&#39;t add the part to the circuit.</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">circuit</span> <span class="o">=</span> <span class="kc">None</span>

            <span class="c1"># Add any net/pin connections to this part that were passed as arguments.</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">connections</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
                <span class="k">for</span> <span class="n">pin</span><span class="p">,</span> <span class="n">net</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">connections</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
                    <span class="n">net</span> <span class="o">+=</span> <span class="bp">self</span><span class="p">[</span><span class="n">pin</span><span class="p">]</span>

        <span class="c1"># Add any XSPICE I/O as pins. (This only happens with SPICE simulations.)</span>
        <span class="n">add_xspice_io</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;io&quot;</span><span class="p">,</span> <span class="p">[]))</span>

        <span class="c1"># Make sure there is a description, even if empty.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">description</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">&quot;description&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">)</span>

        <span class="c1"># Set the part reference if one was explicitly provided.</span>
        <span class="k">if</span> <span class="n">ref</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">ref</span> <span class="o">=</span> <span class="n">ref</span>

        <span class="c1"># Add any pins that were passed in, and make sure they&#39;re associated with the part.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">add_pins</span><span class="p">(</span><span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;pins&quot;</span><span class="p">,</span> <span class="p">[]))</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">associate_pins</span><span class="p">()</span>

        <span class="c1"># If any unit definitions were passed in, then make units.</span>
        <span class="c1"># FIXME: make_unit takes too long because of filtering pin lists.</span>
        <span class="k">for</span> <span class="n">unit_def</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;unit_defs&quot;</span><span class="p">,</span> <span class="p">[]):</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">make_unit</span><span class="p">(</span>
                <span class="n">unit_def</span><span class="p">[</span><span class="s2">&quot;label&quot;</span><span class="p">],</span> <span class="o">*</span><span class="n">unit_def</span><span class="p">[</span><span class="s2">&quot;pin_nums&quot;</span><span class="p">],</span> <span class="n">unit</span><span class="o">=</span><span class="n">unit_def</span><span class="p">[</span><span class="s2">&quot;num&quot;</span><span class="p">]</span>
            <span class="p">)</span>

        <span class="c1"># Add any other passed-in attributes to the part.</span>
        <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">kwargs</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
            <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>

        <span class="c1"># If the part was found using an alias, then substitute the alias for the name in the part.</span>
        <span class="c1"># Only make the substitution if the name is one of the aliases. (It&#39;s possible the part was</span>
        <span class="c1"># found using a regex and we don&#39;t want that entered as an alias.)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">!=</span> <span class="n">name</span> <span class="ow">and</span> <span class="n">name</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">aliases</span><span class="p">:</span>
            <span class="n">part_name</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
            <span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="nb">vars</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
                <span class="k">if</span> <span class="n">v</span> <span class="o">==</span> <span class="n">part_name</span><span class="p">:</span>
                    <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">fields</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
                <span class="k">if</span> <span class="n">v</span> <span class="o">==</span> <span class="n">part_name</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">fields</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">name</span>

        <span class="c1"># Make sure the part name is also included in the list of aliases</span>
        <span class="c1"># because part searching only checks the aliases for name matches.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">aliases</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return a description of the pins on this part as a string.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            str: A formatted string showing the part name, aliases, description and pins.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2"> </span><span class="si">{name}</span><span class="s2"> (</span><span class="si">{aliases}</span><span class="s2">): </span><span class="si">{desc}</span><span class="se">\n</span><span class="s2">    </span><span class="si">{pins}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
            <span class="n">name</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
            <span class="n">aliases</span><span class="o">=</span><span class="s2">&quot;, &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">aliases</span><span class="p">),</span>
            <span class="n">desc</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">description</span><span class="p">,</span>
            <span class="n">pins</span><span class="o">=</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">    &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">p</span><span class="o">.</span><span class="fm">__str__</span><span class="p">()</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">]),</span>
        <span class="p">)</span>

    <span class="fm">__repr__</span> <span class="o">=</span> <span class="fm">__str__</span>

    <span class="k">def</span> <span class="fm">__bool__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Any valid Part is True.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            bool: Always returns True for valid Part objects.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span>

    <span class="n">__nonzero__</span> <span class="o">=</span> <span class="fm">__bool__</span>  <span class="c1"># Python 2 compatibility.</span>

    <span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return the number of pins in this part.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            int: The number of pins in this part.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">)</span>

    <span class="c1"># Make copies with the multiplication operator or by calling the object.</span>
    <span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">num_copies</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">NETLIST</span><span class="p">,</span> <span class="n">circuit</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">io</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">attribs</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Make zero or more copies of this part while maintaining all pin/net connections.</span>

<span class="sd">        Args:</span>
<span class="sd">            num_copies (int, optional): Number of copies to make of this part.</span>
<span class="sd">            dest (str, optional): Indicates where the copy is destined for (e.g., NETLIST).</span>
<span class="sd">            circuit (Circuit, optional): The circuit this part should be added to.</span>
<span class="sd">            io (list, optional): XSPICE I/O names.</span>

<span class="sd">        Keyword Args:</span>
<span class="sd">            attribs: Name/value pairs for setting attributes for the copy.</span>

<span class="sd">        Returns:</span>
<span class="sd">            Part or list: A list of Part copies or a single Part if num_copies==1.</span>

<span class="sd">        Raises:</span>
<span class="sd">            ValueError: If the requested number of copies is a non-integer or negative.</span>

<span class="sd">        Notes:</span>
<span class="sd">            An instance of a part can be copied just by calling it like so::</span>

<span class="sd">                res = Part(&quot;Device&quot;,&#39;R&#39;)    # Get a resistor.</span>
<span class="sd">                res_copy = res(value=&#39;1K&#39;)  # Copy the resistor and set resistance value.</span>

<span class="sd">            You can also use the multiplication operator to make copies::</span>

<span class="sd">                cap = Part(&quot;Device&quot;, &#39;C&#39;)   # Get a capacitor</span>
<span class="sd">                caps = 10 * cap             # Make an array with 10 copies of it.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span>
            <span class="n">num_copies</span><span class="o">=</span><span class="n">num_copies</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">dest</span><span class="p">,</span> <span class="n">circuit</span><span class="o">=</span><span class="n">circuit</span><span class="p">,</span> <span class="n">io</span><span class="o">=</span><span class="n">io</span><span class="p">,</span> <span class="o">**</span><span class="n">attribs</span>
        <span class="p">)</span>

    <span class="k">def</span> <span class="fm">__mul__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">num_copies</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Create multiple copies of a part using the * operator.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            num_copies (int): Number of copies to make.</span>
<span class="sd">            </span>
<span class="sd">        Returns:</span>
<span class="sd">            list: List of part copies.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">num_copies</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">num_copies</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">num_copies</span><span class="o">=</span><span class="n">num_copies</span><span class="p">)</span>

    <span class="fm">__rmul__</span> <span class="o">=</span> <span class="fm">__mul__</span>

    <span class="k">def</span> <span class="fm">__and__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Attach a part and another part/pin/net in serial.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            obj: The object to connect in series with this part.</span>
<span class="sd">            </span>
<span class="sd">        Returns:</span>
<span class="sd">            Network: A network representing the series connection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="kn">from</span> <span class="nn">.network</span> <span class="kn">import</span> <span class="n">Network</span>

        <span class="k">return</span> <span class="n">Network</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">&amp;</span> <span class="n">obj</span>

    <span class="k">def</span> <span class="fm">__rand__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Attach a part and another part/pin/net in serial (right-side operation).</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            obj: The object to connect in series with this part.</span>
<span class="sd">            </span>
<span class="sd">        Returns:</span>
<span class="sd">            Network: A network representing the series connection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="kn">from</span> <span class="nn">.network</span> <span class="kn">import</span> <span class="n">Network</span>

        <span class="k">return</span> <span class="n">obj</span> <span class="o">&amp;</span> <span class="n">Network</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

    <span class="k">def</span> <span class="fm">__or__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Attach a part and another part/pin/net in parallel.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            obj: The object to connect in parallel with this part.</span>
<span class="sd">            </span>
<span class="sd">        Returns:</span>
<span class="sd">            Network: A network representing the parallel connection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="kn">from</span> <span class="nn">.network</span> <span class="kn">import</span> <span class="n">Network</span>

        <span class="k">return</span> <span class="n">Network</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">|</span> <span class="n">obj</span>

    <span class="k">def</span> <span class="fm">__ror__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Attach a part and another part/pin/net in parallel (right-side operation).</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            obj: The object to connect in parallel with this part.</span>
<span class="sd">            </span>
<span class="sd">        Returns:</span>
<span class="sd">            Network: A network representing the parallel connection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="kn">from</span> <span class="nn">.network</span> <span class="kn">import</span> <span class="n">Network</span>

        <span class="k">return</span> <span class="n">obj</span> <span class="o">|</span> <span class="n">Network</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

<div class="viewcode-block" id="Part.get">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.get">[docs]</a>
    <span class="nd">@classmethod</span>
    <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">text</span><span class="p">,</span> <span class="n">circuit</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Get the part with the given text from a circuit, or return None.</span>

<span class="sd">        Args:</span>
<span class="sd">            text (str): A text string that will be searched for in the list of</span>
<span class="sd">                parts.</span>

<span class="sd">        Keyword Args:</span>
<span class="sd">            circuit (Circuit, optional): The circuit whose parts will be searched. If set to None,</span>
<span class="sd">                then the parts in the default_circuit will be searched.</span>

<span class="sd">        Returns:</span>
<span class="sd">            Part or list: A list of parts or a single part that match the text string with</span>
<span class="sd">                either their reference, name, alias, or their description.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">circuit</span> <span class="o">=</span> <span class="n">circuit</span> <span class="ow">or</span> <span class="n">default_circuit</span>

        <span class="n">search_params</span> <span class="o">=</span> <span class="p">(</span>
            <span class="p">(</span><span class="s2">&quot;ref&quot;</span><span class="p">,</span> <span class="n">text</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span>
            <span class="c1"># (&quot;name&quot;, text, True), # Redundant: name is already replicated in aliases.</span>
            <span class="p">(</span><span class="s2">&quot;aliases&quot;</span><span class="p">,</span> <span class="n">text</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span>
            <span class="p">(</span><span class="s2">&quot;description&quot;</span><span class="p">,</span> <span class="n">text</span><span class="p">,</span> <span class="kc">False</span><span class="p">),</span>
        <span class="p">)</span>

        <span class="n">parts</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">attr</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">do_str_match</span> <span class="ow">in</span> <span class="n">search_params</span><span class="p">:</span>
            <span class="n">parts</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span>
                <span class="n">filter_list</span><span class="p">(</span><span class="n">circuit</span><span class="o">.</span><span class="n">parts</span><span class="p">,</span> <span class="n">do_str_match</span><span class="o">=</span><span class="n">do_str_match</span><span class="p">,</span> <span class="o">**</span><span class="p">{</span><span class="n">attr</span><span class="p">:</span> <span class="n">value</span><span class="p">})</span>
            <span class="p">)</span>

        <span class="k">return</span> <span class="n">list_or_scalar</span><span class="p">(</span><span class="n">parts</span><span class="p">)</span></div>


<div class="viewcode-block" id="Part.value_to_str">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.value_to_str">[docs]</a>
    <span class="k">def</span> <span class="nf">value_to_str</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return value of part as a string.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            str: String representation of the part&#39;s value.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">value</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">&quot;value&quot;</span><span class="p">,</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">&quot;name&quot;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">ref_prefix</span><span class="p">))</span>
        <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)</span></div>


<div class="viewcode-block" id="Part.similarity">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.similarity">[docs]</a>
    <span class="k">def</span> <span class="nf">similarity</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">part</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return a measure of how similar two parts are.</span>

<span class="sd">        Args:</span>
<span class="sd">            part (Part): The part to compare to for similarity.</span>
<span class="sd">            options (dict): Dictionary of options and settings affecting similarity computation.</span>

<span class="sd">        Returns:</span>
<span class="sd">            float: Value for similarity (larger means more similar).</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">def</span> <span class="nf">score_pins</span><span class="p">():</span>
            <span class="n">pin_score</span> <span class="o">=</span> <span class="mi">0</span>
            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">part</span><span class="o">.</span><span class="n">pins</span><span class="p">):</span>
                <span class="k">for</span> <span class="n">p_self</span><span class="p">,</span> <span class="n">p_other</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ordered_pins</span><span class="p">,</span> <span class="n">part</span><span class="o">.</span><span class="n">ordered_pins</span><span class="p">):</span>
                    <span class="k">if</span> <span class="n">p_self</span><span class="o">.</span><span class="n">is_attached</span><span class="p">(</span><span class="n">p_other</span><span class="p">):</span>
                        <span class="n">pin_score</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="k">return</span> <span class="n">pin_score</span>

        <span class="c1"># Every part starts off somewhat similar to another.</span>
        <span class="n">score</span> <span class="o">=</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">description</span> <span class="o">==</span> <span class="n">part</span><span class="o">.</span><span class="n">description</span><span class="p">:</span>
            <span class="n">score</span> <span class="o">+=</span> <span class="mi">5</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="n">part</span><span class="o">.</span><span class="n">name</span><span class="p">:</span>
            <span class="n">score</span> <span class="o">+=</span> <span class="mi">5</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">==</span> <span class="n">part</span><span class="o">.</span><span class="n">value</span><span class="p">:</span>
                <span class="n">score</span> <span class="o">+=</span> <span class="mi">2</span>
            <span class="n">score</span> <span class="o">+=</span> <span class="n">score_pins</span><span class="p">()</span>
        <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">ref_prefix</span> <span class="o">==</span> <span class="n">part</span><span class="o">.</span><span class="n">ref_prefix</span><span class="p">:</span>
            <span class="n">score</span> <span class="o">+=</span> <span class="mi">3</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">==</span> <span class="n">part</span><span class="o">.</span><span class="n">value</span><span class="p">:</span>
                <span class="n">score</span> <span class="o">+=</span> <span class="mi">2</span>
            <span class="n">score</span> <span class="o">+=</span> <span class="n">score_pins</span><span class="p">()</span>

        <span class="k">return</span> <span class="n">score</span> <span class="o">/</span> <span class="mi">3</span></div>


<div class="viewcode-block" id="Part.parse">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.parse">[docs]</a>
    <span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">partial_parse</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Create a part from its stored part definition.</span>

<span class="sd">        Args:</span>
<span class="sd">            partial_parse (bool, optional): When true, just get the name and aliases for the</span>
<span class="sd">                part. Leave the rest unparsed. Defaults to False.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="kn">from</span> <span class="nn">.tools</span> <span class="kn">import</span> <span class="n">tool_modules</span>

        <span class="c1"># Parse the part description.</span>
        <span class="n">tool_modules</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">tool</span><span class="p">]</span><span class="o">.</span><span class="n">parse_lib_part</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">partial_parse</span><span class="p">)</span></div>


<div class="viewcode-block" id="Part.copy">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.copy">[docs]</a>
    <span class="k">def</span> <span class="nf">copy</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">num_copies</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">NETLIST</span><span class="p">,</span> <span class="n">circuit</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">io</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">attribs</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Make zero or more copies of this part while maintaining all pin/net connections.</span>

<span class="sd">        Args:</span>
<span class="sd">            num_copies (int, optional): Number of copies to make of this part.</span>
<span class="sd">            dest (str, optional): Indicates where the copy is destined for (e.g., NETLIST).</span>
<span class="sd">            circuit (Circuit, optional): The circuit this part should be added to.</span>
<span class="sd">            io (list, optional): XSPICE I/O names.</span>

<span class="sd">        Keyword Args:</span>
<span class="sd">            attribs: Name/value pairs for setting attributes for the copy.</span>

<span class="sd">        Returns:</span>
<span class="sd">            Part or list: A list of Part copies or a single Part if num_copies==1.</span>

<span class="sd">        Raises:</span>
<span class="sd">            ValueError: If the requested number of copies is a non-integer or negative.</span>

<span class="sd">        Notes:</span>
<span class="sd">            An instance of a part can be copied just by calling it like so::</span>

<span class="sd">                res = Part(&quot;Device&quot;,&#39;R&#39;)    # Get a resistor.</span>
<span class="sd">                res_copy = res(value=&#39;1K&#39;)  # Copy the resistor and set resistance value.</span>

<span class="sd">            You can also use the multiplication operator to make copies::</span>

<span class="sd">                cap = Part(&quot;Device&quot;, &#39;C&#39;)   # Get a capacitor</span>
<span class="sd">                caps = 10 * cap             # Make an array with 10 copies of it.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="kn">from</span> <span class="nn">.circuit</span> <span class="kn">import</span> <span class="n">Circuit</span>
        <span class="kn">from</span> <span class="nn">.part</span> <span class="kn">import</span> <span class="n">NETLIST</span>
        <span class="kn">from</span> <span class="nn">.pin</span> <span class="kn">import</span> <span class="n">Pin</span>
        <span class="kn">from</span> <span class="nn">.tools.spice</span> <span class="kn">import</span> <span class="n">add_xspice_io</span>

        <span class="c1"># If the number of copies is None, then a single copy will be made</span>
        <span class="c1"># and returned as a scalar (not a list). Otherwise, the number of</span>
        <span class="c1"># copies will be set by the num_copies parameter or the number of</span>
        <span class="c1"># values supplied for each part attribute.</span>
        <span class="n">num_copies_attribs</span> <span class="o">=</span> <span class="n">find_num_copies</span><span class="p">(</span><span class="o">**</span><span class="n">attribs</span><span class="p">)</span>
        <span class="n">return_list</span> <span class="o">=</span> <span class="p">(</span><span class="n">num_copies</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">num_copies_attribs</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">num_copies</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">num_copies</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">num_copies_attribs</span><span class="p">)</span>

        <span class="c1"># Check that a valid number of copies is requested.</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">num_copies</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
            <span class="n">active_logger</span><span class="o">.</span><span class="n">raise_</span><span class="p">(</span>
                <span class="ne">ValueError</span><span class="p">,</span>
                <span class="sa">f</span><span class="s2">&quot;Can&#39;t make a non-integer number (</span><span class="si">{</span><span class="n">num_copies</span><span class="si">}</span><span class="s2">) of copies of a part!&quot;</span>
            <span class="p">)</span>
        <span class="k">if</span> <span class="n">num_copies</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">active_logger</span><span class="o">.</span><span class="n">raise_</span><span class="p">(</span>
                <span class="ne">ValueError</span><span class="p">,</span>
                <span class="s2">&quot;Can&#39;t make a negative number (</span><span class="si">{num_copies}</span><span class="s2">) of copies of a part!&quot;</span>
            <span class="p">)</span>

        <span class="c1"># Now make copies of the part one-by-one.</span>
        <span class="n">copies</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_copies</span><span class="p">):</span>

            <span class="c1"># Make a copy of the part.</span>
            <span class="n">cpy</span> <span class="o">=</span> <span class="n">copy</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>  <span class="c1"># Start with shallow copy.</span>
            <span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
                <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="p">(</span><span class="n">Pin</span><span class="p">,</span> <span class="n">PartUnit</span><span class="p">)):</span>
                    <span class="c1"># These require special handling later.</span>
                    <span class="k">continue</span>
                <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
                    <span class="c1"># Copy the list with shallow copies of its items to the copy.</span>
                    <span class="nb">setattr</span><span class="p">(</span><span class="n">cpy</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">copy</span><span class="p">(</span><span class="n">v</span><span class="p">))</span>

            <span class="c1"># Remove any existing part tag so the copy won&#39;t be linked to the</span>
            <span class="c1"># same footprint in the PCB as the source.</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="k">del</span> <span class="n">cpy</span><span class="o">.</span><span class="n">tag</span>
            <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
                <span class="k">pass</span>

            <span class="c1"># Remove any existing Pin and PartUnit attributes so new ones</span>
            <span class="c1"># can be made in the copy without generating warning messages.</span>
            <span class="n">rmv_attrs</span> <span class="o">=</span> <span class="p">[</span>
                <span class="n">k</span>
                <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">cpy</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
                <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="p">(</span><span class="n">Pin</span><span class="p">,</span> <span class="n">PartUnit</span><span class="p">))</span>
            <span class="p">]</span>
            <span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="n">rmv_attrs</span><span class="p">:</span>
                <span class="nb">delattr</span><span class="p">(</span><span class="n">cpy</span><span class="p">,</span> <span class="n">attr</span><span class="p">)</span>

            <span class="c1"># The shallow copy will just put references to the pins of the</span>
            <span class="c1"># original into the copy, so create independent copies of the pins.</span>
            <span class="n">cpy</span><span class="o">.</span><span class="n">pins</span> <span class="o">=</span> <span class="p">[]</span>
            <span class="c1"># Add pin with part attribute set to the newly copied part.</span>
            <span class="n">cpy</span> <span class="o">+=</span> <span class="p">[</span><span class="n">p</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">part</span><span class="o">=</span><span class="n">cpy</span><span class="p">)</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">]</span>

            <span class="c1"># If the part copy is intended as a template, then disconnect its pins</span>
            <span class="c1"># from any circuit nets.</span>
            <span class="k">if</span> <span class="n">dest</span> <span class="o">==</span> <span class="n">TEMPLATE</span><span class="p">:</span>
                <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">cpy</span><span class="o">.</span><span class="n">pins</span><span class="p">:</span>
                    <span class="n">p</span><span class="o">.</span><span class="n">disconnect</span><span class="p">()</span>

            <span class="c1"># Make new objects for searching the copy&#39;s pin numbers and names.</span>
            <span class="n">cpy</span><span class="o">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">PinNumberSearch</span><span class="p">(</span><span class="n">cpy</span><span class="p">)</span>
            <span class="n">cpy</span><span class="o">.</span><span class="n">n</span> <span class="o">=</span> <span class="n">PinNameSearch</span><span class="p">(</span><span class="n">cpy</span><span class="p">)</span>

            <span class="c1"># Copy the part fields from the original.</span>
            <span class="n">cpy</span><span class="o">.</span><span class="n">fields</span> <span class="o">=</span> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">v</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">fields</span><span class="o">.</span><span class="n">items</span><span class="p">()}</span>

            <span class="c1"># Copy part units from the original to the copy.</span>
            <span class="n">cpy</span><span class="o">.</span><span class="n">copy_units</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

            <span class="c1"># Clear the part reference of the copied part so a unique reference</span>
            <span class="c1"># can be assigned when the part is added to the circuit.</span>
            <span class="c1"># (This is not strictly necessary since the part reference will be</span>
            <span class="c1"># adjusted to be unique if needed during the addition process.)</span>
            <span class="n">cpy</span><span class="o">.</span><span class="n">_ref</span> <span class="o">=</span> <span class="kc">None</span>

            <span class="c1"># Copied part starts off not being in any circuit.</span>
            <span class="n">cpy</span><span class="o">.</span><span class="n">circuit</span> <span class="o">=</span> <span class="kc">None</span>

            <span class="c1"># If copy is destined for a netlist, then add it to the Circuit its</span>
            <span class="c1"># source came from or else add it to the default Circuit object.</span>
            <span class="k">if</span> <span class="n">dest</span> <span class="o">==</span> <span class="n">NETLIST</span><span class="p">:</span>
                <span class="c1"># Place the copied part in the explicitly-stated circuit,</span>
                <span class="c1"># or the same circuit as the original,</span>
                <span class="c1"># or else into the default circuit.</span>
                <span class="n">circuit</span> <span class="o">=</span> <span class="n">circuit</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">circuit</span> <span class="ow">or</span> <span class="n">default_circuit</span>
                <span class="n">circuit</span> <span class="o">+=</span> <span class="n">cpy</span>

            <span class="c1"># Add any XSPICE I/O as pins to the part.</span>
            <span class="n">add_xspice_io</span><span class="p">(</span><span class="n">cpy</span><span class="p">,</span> <span class="n">io</span><span class="p">)</span>

            <span class="c1"># Enter any new attributes.</span>
            <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">attribs</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
                <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">)):</span>
                    <span class="k">try</span><span class="p">:</span>
                        <span class="n">v</span> <span class="o">=</span> <span class="n">v</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
                    <span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span>
                        <span class="n">active_logger</span><span class="o">.</span><span class="n">raise_</span><span class="p">(</span>
                            <span class="ne">ValueError</span><span class="p">,</span>
                            <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">num_copies</span><span class="si">}</span><span class="s2"> copies of part </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> were requested, but too few elements in attribute </span><span class="si">{</span><span class="n">k</span><span class="si">}</span><span class="s2">!&quot;</span>
                        <span class="p">)</span>
                <span class="nb">setattr</span><span class="p">(</span><span class="n">cpy</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>

            <span class="c1"># Add the part copy to the list of copies.</span>
            <span class="n">copies</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cpy</span><span class="p">)</span>

        <span class="c1"># Return a list of the copies made or just a single copy.</span>
        <span class="k">if</span> <span class="n">return_list</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">copies</span>
        <span class="k">return</span> <span class="n">copies</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></div>


<div class="viewcode-block" id="Part.validate">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.validate">[docs]</a>
    <span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Check that pins and units reference the correct part that owns them.</span>
<span class="sd">        </span>
<span class="sd">        Raises:</span>
<span class="sd">            AssertionError: If pins or units don&#39;t properly reference this part.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">for</span> <span class="n">pin</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">:</span>
            <span class="k">assert</span> <span class="n">pin</span><span class="o">.</span><span class="n">part</span> <span class="o">==</span> <span class="bp">self</span>
        <span class="k">for</span> <span class="n">unit</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">unit</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
            <span class="c1"># A Part can be a unit of itself, so don&#39;t validate it to avoid infinite recursion.</span>
            <span class="k">if</span> <span class="n">unit</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">self</span><span class="p">:</span>
                <span class="n">unit</span><span class="o">.</span><span class="n">validate</span><span class="p">()</span></div>


<div class="viewcode-block" id="Part.copy_units">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.copy_units">[docs]</a>
    <span class="k">def</span> <span class="nf">copy_units</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Make copies of the units from the source part.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            src (Part): The source part containing units to copy.</span>
<span class="sd">            </span>
<span class="sd">        Raises:</span>
<span class="sd">            Exception: If an illegal unit type is encountered.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">unit</span> <span class="o">=</span> <span class="p">{}</span>  <span class="c1"># Remove references to any existing units.</span>
        <span class="k">for</span> <span class="n">label</span><span class="p">,</span> <span class="n">unit</span> <span class="ow">in</span> <span class="n">src</span><span class="o">.</span><span class="n">unit</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">unit</span><span class="p">,</span> <span class="n">PartUnit</span><span class="p">):</span>
                <span class="c1"># Get the pin numbers from the unit in the source part</span>
                <span class="c1"># and make a unit in the part copy with the same pin numbers.</span>
                <span class="n">pin_nums</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span><span class="o">.</span><span class="n">num</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">unit</span><span class="o">.</span><span class="n">pins</span><span class="p">]</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">make_unit</span><span class="p">(</span><span class="n">label</span><span class="p">,</span> <span class="o">*</span><span class="n">pin_nums</span><span class="p">,</span> <span class="n">unit</span><span class="o">=</span><span class="n">unit</span><span class="o">.</span><span class="n">num</span><span class="p">)</span>
            <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">unit</span><span class="p">,</span> <span class="n">Part</span><span class="p">):</span>
                <span class="c1"># A Part can be a unit of itself, so it requires special handling.</span>
                <span class="k">assert</span> <span class="nb">id</span><span class="p">(</span><span class="n">unit</span><span class="p">)</span> <span class="o">==</span> <span class="nb">id</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">unit</span><span class="p">[</span><span class="n">label</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">unit</span><span class="p">[</span><span class="n">label</span><span class="p">]</span><span class="o">.</span><span class="n">num</span> <span class="o">=</span> <span class="n">unit</span><span class="o">.</span><span class="n">num</span>
                <span class="n">add_unique_attr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">label</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Illegal unit type (</span><span class="si">{</span><span class="nb">type</span><span class="p">(</span><span class="n">unit</span><span class="p">)</span><span class="si">}</span><span class="s2">).&quot;</span><span class="p">)</span></div>


<div class="viewcode-block" id="Part.is_connected">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.is_connected">[docs]</a>
    <span class="k">def</span> <span class="nf">is_connected</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return T/F depending upon whether a part is connected in a netlist.</span>

<span class="sd">        If a part has pins but none of them are connected to nets, then</span>
<span class="sd">        this method will return False. Otherwise, it will return True even if</span>
<span class="sd">        the part has no pins (which can be the case for mechanical parts,</span>
<span class="sd">        silkscreen logos, or other non-electrical schematic elements).</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            bool: True if the part is connected or has no pins, False otherwise.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># Assume parts without pins (like mech. holes) are always connected.</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="kc">True</span>

        <span class="c1"># If any pin is found to be connected to a net, return True.</span>
        <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">is_connected</span><span class="p">():</span>
                <span class="k">return</span> <span class="kc">True</span>

        <span class="c1"># No net connections found, so return False.</span>
        <span class="k">return</span> <span class="kc">False</span></div>


<div class="viewcode-block" id="Part.attached_to">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.attached_to">[docs]</a>
    <span class="k">def</span> <span class="nf">attached_to</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nets</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return True if any part pin is connected to a net in the list.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            nets (list, optional): List of nets to check for connection.</span>
<span class="sd">            </span>
<span class="sd">        Returns:</span>
<span class="sd">            bool: True if part is connected to any of the nets, False otherwise.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">nets</span><span class="p">:</span>
            <span class="k">return</span> <span class="kc">False</span>

        <span class="k">for</span> <span class="n">pin</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">net</span> <span class="ow">in</span> <span class="n">pin</span><span class="o">.</span><span class="n">nets</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">net</span> <span class="ow">in</span> <span class="n">nets</span><span class="p">:</span>
                    <span class="k">return</span> <span class="kc">True</span>
        <span class="k">return</span> <span class="kc">False</span></div>


<div class="viewcode-block" id="Part.is_movable">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.is_movable">[docs]</a>
    <span class="k">def</span> <span class="nf">is_movable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return T/F if the part can be moved from one circuit into another.</span>

<span class="sd">        This method returns true if:</span>
<span class="sd">            1) the part is not in a circuit, or</span>
<span class="sd">            2) the part has pins but none of them are connected to nets, or</span>
<span class="sd">            3) the part has no pins (which can be the case for mechanical parts,</span>
<span class="sd">               silkscreen logos, or other non-electrical schematic elements).</span>
<span class="sd">               </span>
<span class="sd">        Returns:</span>
<span class="sd">            bool: True if the part can be moved to another circuit, False otherwise.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="kn">from</span> <span class="nn">.circuit</span> <span class="kn">import</span> <span class="n">Circuit</span>

        <span class="k">return</span> <span class="p">(</span>
            <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">circuit</span><span class="p">,</span> <span class="n">Circuit</span><span class="p">)</span>
            <span class="ow">or</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_connected</span><span class="p">()</span>
            <span class="ow">or</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span>
        <span class="p">)</span></div>


<div class="viewcode-block" id="Part.make_unit">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.make_unit">[docs]</a>
    <span class="k">def</span> <span class="nf">make_unit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">label</span><span class="p">,</span> <span class="o">*</span><span class="n">pin_ids</span><span class="p">,</span> <span class="o">**</span><span class="n">criteria</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Create a PartUnit from a set of pins in a Part object.</span>

<span class="sd">        Parts can be organized into smaller pieces called PartUnits. A PartUnit</span>
<span class="sd">        acts like a Part but contains only a subset of the pins of the Part.</span>

<span class="sd">        Args:</span>
<span class="sd">            label (str): The label used to identify the PartUnit.</span>
<span class="sd">            pin_ids: A list of strings containing pin names, numbers,</span>
<span class="sd">                regular expressions, slices, lists or tuples.</span>

<span class="sd">        Keyword Args:</span>
<span class="sd">            criteria: Key/value pairs that specify attribute values the</span>
<span class="sd">                pin must have in order to be selected.</span>

<span class="sd">        Returns:</span>
<span class="sd">            PartUnit: The newly created part unit.</span>
<span class="sd">            </span>
<span class="sd">        Warning:</span>
<span class="sd">            Will issue a warning if the unit label collides with any part pin names.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># Warn if the unit label collides with any of the part&#39;s pin names.</span>
        <span class="n">collisions</span> <span class="o">=</span> <span class="p">[</span><span class="n">pin</span> <span class="k">for</span> <span class="n">pin</span> <span class="ow">in</span> <span class="bp">self</span> <span class="k">if</span> <span class="n">pin</span><span class="o">.</span><span class="n">aliases</span> <span class="o">==</span> <span class="n">label</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">collisions</span><span class="p">:</span>
            <span class="n">active_logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
                <span class="sa">f</span><span class="s2">&quot;Using a label (</span><span class="si">{</span><span class="n">label</span><span class="si">}</span><span class="s2">) for a unit of </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">erc_desc</span><span class="p">()</span><span class="si">}</span><span class="s2"> that matches one or more of it&#39;s pin names (</span><span class="si">{</span><span class="n">collisions</span><span class="si">}</span><span class="s2">)!&quot;</span>
            <span class="p">)</span>

        <span class="c1"># Create the part unit.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">unit</span><span class="p">[</span><span class="n">label</span><span class="p">]</span> <span class="o">=</span> <span class="n">PartUnit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">label</span><span class="p">,</span> <span class="o">*</span><span class="n">pin_ids</span><span class="p">,</span> <span class="o">**</span><span class="n">criteria</span><span class="p">)</span>

        <span class="c1"># Add a unique identifier to the unit.</span>
        <span class="n">add_unique_attr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">label</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">unit</span><span class="p">[</span><span class="n">label</span><span class="p">])</span>

        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">unit</span><span class="p">[</span><span class="n">label</span><span class="p">]</span></div>


<div class="viewcode-block" id="Part.rmv_unit">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.rmv_unit">[docs]</a>
    <span class="k">def</span> <span class="nf">rmv_unit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">label</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Remove a PartUnit from a Part.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            label (str): Label of unit to remove.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="nb">delattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">label</span><span class="p">)</span>
        <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">unit</span><span class="p">[</span><span class="n">label</span><span class="p">]</span></div>


<div class="viewcode-block" id="Part.grab_pins">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.grab_pins">[docs]</a>
    <span class="k">def</span> <span class="nf">grab_pins</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Grab pins back from PartUnits.</span>
<span class="sd">        </span>
<span class="sd">        Makes each unit release its pins back to the part that contains it.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># Make each unit release its pins back to the part that contains it.</span>
        <span class="k">for</span> <span class="n">unit</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">unit</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
            <span class="n">unit</span><span class="o">.</span><span class="n">release_pins</span><span class="p">()</span></div>


<div class="viewcode-block" id="Part.release_pins">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.release_pins">[docs]</a>
    <span class="k">def</span> <span class="nf">release_pins</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        A Part can&#39;t release pins back to its PartUnits, so do nothing.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">pass</span></div>


<div class="viewcode-block" id="Part.create_network">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.create_network">[docs]</a>
    <span class="k">def</span> <span class="nf">create_network</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Create a network from the pins of a part.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            Network: A network containing the part&#39;s pins.</span>
<span class="sd">            </span>
<span class="sd">        Raises:</span>
<span class="sd">            Exception: If the part has more than 2 pins.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="kn">from</span> <span class="nn">.network</span> <span class="kn">import</span> <span class="n">Network</span>

        <span class="n">ntwk</span> <span class="o">=</span> <span class="n">Network</span><span class="p">(</span><span class="bp">self</span><span class="p">[:])</span>  <span class="c1"># An error will occur if part has more than 2 pins.</span>
        <span class="k">return</span> <span class="n">ntwk</span></div>


<div class="viewcode-block" id="Part.generate_svg_component">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.generate_svg_component">[docs]</a>
    <span class="k">def</span> <span class="nf">generate_svg_component</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">symtx</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">tool</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">net_stubs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Generate the SVG for displaying a part in an SVG schematic.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            symtx (str, optional): Transform for the SVG symbol. Defaults to &quot;&quot;.</span>
<span class="sd">            tool (str, optional): Tool format to use for SVG generation. Defaults to config.tool.</span>
<span class="sd">            net_stubs (list, optional): List of net stubs to include in the SVG.</span>
<span class="sd">            </span>
<span class="sd">        Returns:</span>
<span class="sd">            str: SVG representation of the component.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="kn">import</span> <span class="nn">skidl</span>

        <span class="kn">from</span> <span class="nn">.tools</span> <span class="kn">import</span> <span class="n">tool_modules</span>

        <span class="n">tool</span> <span class="o">=</span> <span class="n">tool</span> <span class="ow">or</span> <span class="n">skidl</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">tool</span>

        <span class="k">return</span> <span class="n">tool_modules</span><span class="p">[</span><span class="n">tool</span><span class="p">]</span><span class="o">.</span><span class="n">gen_svg_comp</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">symtx</span><span class="o">=</span><span class="n">symtx</span><span class="p">,</span> <span class="n">net_stubs</span><span class="o">=</span><span class="n">net_stubs</span><span class="p">)</span></div>


<div class="viewcode-block" id="Part.erc_desc">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.erc_desc">[docs]</a>
    <span class="k">def</span> <span class="nf">erc_desc</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Create description of part for ERC and other error reporting.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            str: A string description in the form &quot;name/ref&quot;</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">/</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">ref</span><span class="si">}</span><span class="s2">&quot;</span></div>


<div class="viewcode-block" id="Part.export">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.export">[docs]</a>
    <span class="k">def</span> <span class="nf">export</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">addtl_part_attrs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return a string to recreate a Part object.</span>

<span class="sd">        Args:</span>
<span class="sd">            addtl_part_attrs (list, optional): List of additional part attribute names to include in export.</span>

<span class="sd">        Returns:</span>
<span class="sd">            str: String that can be evaluated to rebuild the Part object.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># Make sure the part is fully instantiated. Otherwise, attributes like</span>
        <span class="c1"># pins may be missing because they haven&#39;t been parsed from the part definition.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">parse</span><span class="p">()</span>

        <span class="c1"># List of attributes to export that are necessary for rebuilding a part.</span>
        <span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
            <span class="s2">&quot;aliases&quot;</span><span class="p">,</span>
            <span class="s2">&quot;ref_prefix&quot;</span><span class="p">,</span>
            <span class="s2">&quot;fplist&quot;</span><span class="p">,</span>
            <span class="s2">&quot;footprint&quot;</span><span class="p">,</span>
            <span class="s2">&quot;keywords&quot;</span><span class="p">,</span>
            <span class="s2">&quot;description&quot;</span><span class="p">,</span>
            <span class="s2">&quot;datasheet&quot;</span><span class="p">,</span>
        <span class="p">]</span>

        <span class="c1"># Add any other additional part attributes</span>
        <span class="k">if</span> <span class="n">addtl_part_attrs</span><span class="p">:</span>
            <span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">addtl_part_attrs</span><span class="p">)</span>

        <span class="c1"># Export the part as a SKiDL template.</span>
        <span class="n">attribs</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">attribs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;&#39;name&#39;:</span><span class="si">{</span><span class="nb">repr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
        <span class="n">attribs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;&#39;dest&#39;:TEMPLATE&quot;</span><span class="p">)</span>
        <span class="n">attribs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;&#39;tool&#39;:SKIDL&quot;</span><span class="p">)</span>

        <span class="c1"># Collect all the part attributes and the list of pins and units as Python code.</span>
        <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">keys</span><span class="p">:</span>
            <span class="n">v</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
            <span class="n">attribs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;&#39;</span><span class="si">{</span><span class="n">k</span><span class="si">}</span><span class="s2">&#39;:</span><span class="si">{</span><span class="nb">repr</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">:</span>
            <span class="n">pin_strs</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span><span class="o">.</span><span class="n">export</span><span class="p">()</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">]</span>
            <span class="n">attribs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;&#39;pins&#39;:[</span><span class="si">{}</span><span class="s2">]&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">pin_strs</span><span class="p">)))</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">unit</span><span class="p">:</span>
            <span class="c1"># TODO: How to handle a Part that is also a unit?</span>
            <span class="n">unit_strs</span> <span class="o">=</span> <span class="p">[</span>
                <span class="n">unit</span><span class="o">.</span><span class="n">export</span><span class="p">()</span>
                <span class="k">for</span> <span class="n">unit</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">unit</span><span class="o">.</span><span class="n">values</span><span class="p">()</span>
                <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">unit</span><span class="p">,</span> <span class="n">PartUnit</span><span class="p">)</span>
            <span class="p">]</span>
            <span class="n">attribs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;&#39;unit_defs&#39;:[</span><span class="si">{}</span><span class="s2">]&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">unit_strs</span><span class="p">)))</span>

        <span class="c1"># Return the string after removing all the non-ascii stuff (like ohm symbols).</span>
        <span class="c1"># This string is a Part instantiation with parameters that will create the part when executed.</span>
        <span class="k">return</span> <span class="s2">&quot;Part(**{{ </span><span class="si">{}</span><span class="s2"> }})&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s2">&quot;, &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">attribs</span><span class="p">))</span></div>


<div class="viewcode-block" id="Part.convert_for_spice">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.Part.convert_for_spice">[docs]</a>
    <span class="k">def</span> <span class="nf">convert_for_spice</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">spice_part</span><span class="p">,</span> <span class="n">pin_map</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Convert a Part object for use with SPICE.</span>

<span class="sd">        Args:</span>
<span class="sd">            spice_part (Part): The type of SPICE Part to be converted to.</span>
<span class="sd">            pin_map (dict): Dict with pin numbers/names of self as keys and num/names of spice_part pins as replacement values.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="kn">from</span> <span class="nn">.tools.spice</span> <span class="kn">import</span> <span class="n">convert_for_spice</span>

        <span class="n">convert_for_spice</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">spice_part</span><span class="p">,</span> <span class="n">pin_map</span><span class="p">)</span></div>


    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">ref</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Get the part reference.</span>

<span class="sd">        When setting the part reference, if another part with the same</span>
<span class="sd">        reference is found, the reference for this part is adjusted to make</span>
<span class="sd">        it unique.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            str: The part&#39;s reference designator.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_ref</span>

    <span class="nd">@ref</span><span class="o">.</span><span class="n">setter</span>
    <span class="k">def</span> <span class="nf">ref</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">r</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Set the part&#39;s reference.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            r (str): The reference to assign to the part.</span>
<span class="sd">            </span>
<span class="sd">        Notes:</span>
<span class="sd">            If the reference would conflict with another part, a unique</span>
<span class="sd">            variation will be generated.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c1"># Remove the existing reference so it doesn&#39;t cause a collision if the</span>
        <span class="c1"># object is renamed with its existing name.</span>
        <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">ref</span>

        <span class="c1"># Now name the object with the given reference or some variation</span>
        <span class="c1"># of it that doesn&#39;t collide with anything else in the list.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_ref</span> <span class="o">=</span> <span class="n">get_unique_name</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">circuit</span><span class="o">.</span><span class="n">parts</span><span class="p">,</span> <span class="s2">&quot;ref&quot;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">ref_prefix</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>
        <span class="k">return</span>

    <span class="nd">@ref</span><span class="o">.</span><span class="n">deleter</span>
    <span class="k">def</span> <span class="nf">ref</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Delete the part reference.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">rmv_unique_name</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">circuit</span><span class="o">.</span><span class="n">parts</span><span class="p">,</span> <span class="s2">&quot;ref&quot;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_ref</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_ref</span> <span class="o">=</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Get the part value.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            str: The part&#39;s value, or part name if no value is set.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span>
        <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
            <span class="c1"># If part has no value, return its part name as the value. This is</span>
            <span class="c1"># done in KiCad where a resistor value is set to &#39;R&#39; if no</span>
            <span class="c1"># explicit value was set.</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>

    <span class="nd">@value</span><span class="o">.</span><span class="n">setter</span>
    <span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Set the part value.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            value: The value to assign to the part.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_value</span> <span class="o">=</span> <span class="n">value</span>

    <span class="nd">@value</span><span class="o">.</span><span class="n">deleter</span>
    <span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Delete the part value.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_value</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">foot</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Get the part footprint.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            str: The part&#39;s footprint.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_foot</span>

    <span class="nd">@foot</span><span class="o">.</span><span class="n">setter</span>
    <span class="k">def</span> <span class="nf">foot</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">footprint</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Set the part footprint.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            footprint (str): The footprint to assign to the part.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_foot</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">footprint</span><span class="p">)</span>

    <span class="nd">@foot</span><span class="o">.</span><span class="n">deleter</span>
    <span class="k">def</span> <span class="nf">foot</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Delete the part footprint.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_foot</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">hiertuple</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return a tuple of the node&#39;s hierarchy path names from top-most node to this one (self).</span>
<span class="sd">        </span>
<span class="sd">        This provides a string representation of the hierarchical path by extracting</span>
<span class="sd">        the names from each node in the hierarchy chain.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            tuple: A tuple of strings representing the names of nodes in the</span>
<span class="sd">                  hierarchical path from root to this node.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">node</span><span class="o">.</span><span class="n">hiertuple</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">tag_ref_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return the tag, reference, or name of an object.</span>

<span class="sd">        This provides a way to retrieve the most relevant identifier for the object.</span>
<span class="sd">        If the tag is set, it will be returned. Otherwise, if the reference is set,</span>
<span class="sd">        it will be returned. If all else fails, the name will be returned.</span>

<span class="sd">        Returns:</span>
<span class="sd">            str: The tag, reference, or name of the object.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">&quot;tag&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="ow">or</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">&quot;ref&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="ow">or</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">&quot;name&quot;</span><span class="p">)</span>
    
    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">hiertuple</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">node</span><span class="o">.</span><span class="n">hiertuple</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">hiername</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return the hierarchical name of the part.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            str: The hierarchical name including hierarchy prefix and tag.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">return</span> <span class="n">HIER_SEP</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">hiertuple</span> <span class="o">+</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">tag_ref_name</span><span class="p">,))</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">partclasses</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Get all part classes associated with this part.</span>

<span class="sd">        Returns the combined set of part classes from both the hierarchical nodes</span>
<span class="sd">        surrounding this part and the part classes directly assigned to this part.</span>

<span class="sd">        Returns:</span>
<span class="sd">            set: A set containing all part classes from the node hierarchy and </span>
<span class="sd">                the part&#39;s directly assigned classes.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c1"># Add all the part classes for all the hierarchical nodes surrounding this part.</span>
        <span class="n">total_partclasses</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">node</span><span class="o">.</span><span class="n">partclasses</span>

        <span class="c1"># Add the part classes directly assigned to this part.</span>
        <span class="n">total_partclasses</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_partclasses</span><span class="p">)</span>
        
        <span class="k">return</span> <span class="n">total_partclasses</span>

    <span class="nd">@partclasses</span><span class="o">.</span><span class="n">setter</span>
    <span class="k">def</span> <span class="nf">partclasses</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">partclasses</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Add one or more part classes to this part&#39;s collection of part classes.</span>

<span class="sd">        Args:</span>
<span class="sd">            *partclasses: Variable number of part class objects to be added to this part&#39;s</span>
<span class="sd">                         part classes collection. Each part class will be associated with</span>
<span class="sd">                         this part&#39;s circuit.</span>

<span class="sd">        Returns:</span>
<span class="sd">            None</span>

<span class="sd">        Note:</span>
<span class="sd">            The part classes are added to the internal _partclasses collection and</span>
<span class="sd">            automatically associated with the current circuit context.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_partclasses</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">partclasses</span><span class="p">,</span> <span class="n">circuit</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">circuit</span><span class="p">)</span>

    <span class="nd">@partclasses</span><span class="o">.</span><span class="n">deleter</span>
    <span class="k">def</span> <span class="nf">partclasses</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Replace existing list of part classes with an empty PartClasses.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_partclasses</span> <span class="o">=</span> <span class="n">PartClasses</span><span class="p">()</span></div>



<div class="viewcode-block" id="PartUnit">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.PartUnit">[docs]</a>
<span class="nd">@export_to_all</span>
<span class="k">class</span> <span class="nc">PartUnit</span><span class="p">(</span><span class="n">Part</span><span class="p">):</span>
<span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Create a PartUnit from a set of pins in a Part object.</span>

<span class="sd">    Parts can be organized into smaller pieces called PartUnits. A PartUnit</span>
<span class="sd">    acts like a Part but contains only a subset of the pins of the Part.</span>
<span class="sd">    Except for the pins, the PartUnit is a shallow copy of the Part and</span>
<span class="sd">    cannot store any other unique data.</span>

<span class="sd">    Args:</span>
<span class="sd">        part (Part): This is the parent Part whose pins the PartUnit is built from.</span>
<span class="sd">        label (str): A unique label for this unit.</span>
<span class="sd">        pin_ids: A list of strings containing pin names, numbers,</span>
<span class="sd">            regular expressions, slices, lists or tuples. If empty, it</span>
<span class="sd">            will match *every* pin of the part.</span>

<span class="sd">    Keyword Args:</span>
<span class="sd">        criteria: Key/value pairs that specify attribute values the</span>
<span class="sd">            pin must have in order to be selected.</span>
<span class="sd">        unit (int): Unit number assigned to this PartUnit. Defaults to 1.</span>

<span class="sd">    Examples:</span>
<span class="sd">        This will return unit 1 from a part::</span>

<span class="sd">            lm358 = Part(&#39;linear&#39;,&#39;lm358&#39;)</span>
<span class="sd">            lm358a = PartUnit(lm358, unit=1)</span>

<span class="sd">        Or you can specify the pins directly::</span>

<span class="sd">            lm358a = PartUnit(lm358, 1, 2, 3)</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parent</span><span class="p">,</span> <span class="n">label</span><span class="p">,</span> <span class="o">*</span><span class="n">pin_ids</span><span class="p">,</span> <span class="o">**</span><span class="n">criteria</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Initialize a PartUnit with pins selected from a parent part.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            parent (Part): Parent part to get pins from.</span>
<span class="sd">            label (str): Label for this unit.</span>
<span class="sd">            pin_ids: Pin names/numbers to include in this unit.</span>
<span class="sd">            </span>
<span class="sd">        Keyword Args:</span>
<span class="sd">            criteria: Key/value pairs for selecting pins.</span>
<span class="sd">            unit (int): Unit number. Defaults to 1.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="kn">from</span> <span class="nn">.pin</span> <span class="kn">import</span> <span class="n">Pin</span>

        <span class="c1"># Don&#39;t use super() for this.</span>
        <span class="n">SkidlBaseObject</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

        <span class="c1"># Remember the part that this unit belongs to.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">parent</span> <span class="o">=</span> <span class="n">parent</span>

        <span class="c1"># Store the part unit label.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">label</span> <span class="o">=</span> <span class="n">label</span>

        <span class="c1"># Store the part unit number if it&#39;s given, otherwise default to 1.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">num</span> <span class="o">=</span> <span class="n">criteria</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;unit&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

        <span class="c1"># Give the PartUnit the same information as the Part it is generated</span>
        <span class="c1"># from so it can act the same way, just with fewer pins.</span>
        <span class="c1"># Do we need this if we define __getattr__ as below?</span>
        <span class="c1"># Yes, since we&#39;re no longer using the __getattr__ shown below.</span>
        <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">parent</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
            <span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span>

        <span class="c1"># Setup the pin number and name search objects for this unit</span>
        <span class="c1"># so the equivalent ones in the parent aren&#39;t used which will search</span>
        <span class="c1"># *all* pins rather than just the unit&#39;s pins.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">p</span> <span class="o">=</span> <span class="n">PinNumberSearch</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">n</span> <span class="o">=</span> <span class="n">PinNameSearch</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

        <span class="c1"># Don&#39;t associate any units from the parent with this unit itself.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">unit</span> <span class="o">=</span> <span class="p">{}</span>

        <span class="c1"># Remove the pins copied from the parent and replace them with</span>
        <span class="c1"># pins selected from the parent.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">pins</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="c1"># A unit may have no pins but gets them from the global unit 0,</span>
        <span class="c1"># so suppress errors if no pins from this unit are found.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">add_pins_from_parent</span><span class="p">(</span><span class="o">*</span><span class="n">pin_ids</span><span class="p">,</span> <span class="n">silent</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="o">**</span><span class="n">criteria</span><span class="p">)</span>

        <span class="c1"># Now Add pins from the global unit 0. Suppress errors if it doesn&#39;t exist.</span>
        <span class="c1"># TODO: KiCad uses unit 0 for global unit. What about other tools?</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">add_pins_from_parent</span><span class="p">(</span><span class="n">unit</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">silent</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>

    <span class="c1">#</span>
    <span class="c1"># This was commented-out because it led to infinite recursion when pickling libraries.</span>
    <span class="c1">#</span>
    <span class="c1"># def __getattr__(self, key):</span>
    <span class="c1">#     &quot;&quot;&quot;Return attribute from parent Part if it wasn&#39;t found in the PartUnit.&quot;&quot;&quot;</span>
    <span class="c1">#     # FIXME: This allows the unit to access *all* the attributes of the parent</span>
    <span class="c1">#     #        even those it shouldn&#39;t be able to (like pins not assigned to it).</span>
    <span class="c1">#     return getattr(self.parent, key)</span>

<div class="viewcode-block" id="PartUnit.add_pins_from_parent">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.PartUnit.add_pins_from_parent">[docs]</a>
    <span class="k">def</span> <span class="nf">add_pins_from_parent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">pin_ids</span><span class="p">,</span> <span class="o">**</span><span class="n">criteria</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Add selected pins from the parent to the part unit.</span>
<span class="sd">        </span>
<span class="sd">        Args:</span>
<span class="sd">            pin_ids: Pin names/numbers to add from parent.</span>
<span class="sd">            </span>
<span class="sd">        Keyword Args:</span>
<span class="sd">            criteria: Key/value pairs for selecting pins.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># Get new pins selected from the parent.</span>
        <span class="n">new_pins</span> <span class="o">=</span> <span class="n">to_list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">get_pins</span><span class="p">(</span><span class="o">*</span><span class="n">pin_ids</span><span class="p">,</span> <span class="o">**</span><span class="n">criteria</span><span class="p">))</span>
        <span class="c1"># Remove None if that&#39;s gotten into the list.</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">new_pins</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
            <span class="k">pass</span>

        <span class="c1"># Add attributes (via aliases) for accessing the new pins.</span>
        <span class="k">for</span> <span class="n">pin</span> <span class="ow">in</span> <span class="n">new_pins</span><span class="p">:</span>
            <span class="n">pin</span><span class="o">.</span><span class="n">aliases</span> <span class="o">+=</span> <span class="n">pin</span><span class="o">.</span><span class="n">name</span>
            <span class="n">pin</span><span class="o">.</span><span class="n">aliases</span> <span class="o">+=</span> <span class="s2">&quot;p&quot;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">pin</span><span class="o">.</span><span class="n">num</span><span class="p">)</span>

        <span class="c1"># Add new pins to existing pins of the unit, removing duplicates.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">pins</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pins</span> <span class="o">+</span> <span class="n">new_pins</span><span class="p">))</span></div>


<div class="viewcode-block" id="PartUnit.validate">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.PartUnit.validate">[docs]</a>
    <span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Check that unit pins point to the parent part.</span>
<span class="sd">        </span>
<span class="sd">        Raises:</span>
<span class="sd">            AssertionError: If pins don&#39;t refer to the parent part.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">for</span> <span class="n">pin</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">:</span>
            <span class="k">assert</span> <span class="nb">id</span><span class="p">(</span><span class="n">pin</span><span class="o">.</span><span class="n">part</span><span class="p">)</span> <span class="o">==</span> <span class="nb">id</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="p">)</span></div>


<div class="viewcode-block" id="PartUnit.grab_pins">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.PartUnit.grab_pins">[docs]</a>
    <span class="k">def</span> <span class="nf">grab_pins</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Grab pin from Part and assign to PartUnit.</span>
<span class="sd">        </span>
<span class="sd">        This changes each pin&#39;s part reference to point to this unit.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">for</span> <span class="n">pin</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">:</span>
            <span class="n">pin</span><span class="o">.</span><span class="n">part</span> <span class="o">=</span> <span class="bp">self</span></div>


<div class="viewcode-block" id="PartUnit.release_pins">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.PartUnit.release_pins">[docs]</a>
    <span class="k">def</span> <span class="nf">release_pins</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return PartUnit pins to parent Part.</span>
<span class="sd">        </span>
<span class="sd">        This changes each pin&#39;s part reference to point back to the parent part.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">for</span> <span class="n">pin</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">:</span>
            <span class="n">pin</span><span class="o">.</span><span class="n">part</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent</span></div>


<div class="viewcode-block" id="PartUnit.export">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.PartUnit.export">[docs]</a>
    <span class="k">def</span> <span class="nf">export</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return a string describing the PartUnit for exporting purposes.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            str: Dictionary representation of the unit as a string.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">d</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;label&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">label</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;num&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">num</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;pin_nums&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">pin</span><span class="o">.</span><span class="n">num</span> <span class="k">for</span> <span class="n">pin</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pins</span><span class="p">]</span>
        <span class="k">return</span> <span class="nb">repr</span><span class="p">(</span><span class="n">d</span><span class="p">)</span></div>


    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">ref</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Get the unit&#39;s hierarchical reference.</span>
<span class="sd">        </span>
<span class="sd">        Returns:</span>
<span class="sd">            str: Reference in the form &quot;parent_ref.label&quot;</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">HIER_SEP</span><span class="o">.</span><span class="n">join</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">ref</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">label</span><span class="p">))</span>
    
    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">hiertuple</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">hiertuple</span></div>



<span class="n">PartTmplt</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">Part</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
<span class="n">PartTmplt</span><span class="o">.</span><span class="vm">__doc__</span> <span class="o">=</span> <span class="s2">&quot;&quot;&quot;</span>
<span class="s2">    Shortcut for creating a Part template.</span>
<span class="s2">    </span>
<span class="s2">    Creates a Part that is not added to the default circuit.</span>
<span class="s2">    &quot;&quot;&quot;</span>

<span class="n">SkidlPart</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">Part</span><span class="p">,</span> <span class="n">tool</span><span class="o">=</span><span class="s2">&quot;skidl&quot;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
<span class="n">SkidlPart</span><span class="o">.</span><span class="vm">__doc__</span> <span class="o">=</span> <span class="s2">&quot;&quot;&quot; </span>
<span class="s2">    A class for storing a SKiDL definition of a schematic part.</span>
<span class="s2">    </span>
<span class="s2">    It&#39;s identical to its Part superclass except:</span>

<span class="s2">    + The tool defaults to SKIDL.</span>
<span class="s2">    + The destination defaults to TEMPLATE so that it&#39;s easier to start</span>
<span class="s2">        a part and then add pins to it without it being added to the netlist.</span>
<span class="s2">    &quot;&quot;&quot;</span>


<div class="viewcode-block" id="default_empty_footprint_handler">
<a class="viewcode-back" href="../../rst_output/skidl.part.html#skidl.part.default_empty_footprint_handler">[docs]</a>
<span class="nd">@export_to_all</span>
<span class="k">def</span> <span class="nf">default_empty_footprint_handler</span><span class="p">(</span><span class="n">part</span><span class="p">):</span>
<span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Handle the situation of a Part with no footprint when generating netlist/PCB.</span>

<span class="sd">    Args:</span>
<span class="sd">        part (Part): The part with no footprint.</span>

<span class="sd">    Note:</span>
<span class="sd">        By default, this function logs an error message if the footprint is missing.</span>
<span class="sd">        Override this function if you want to try and set some default footprint</span>
<span class="sd">        for particular types of parts (such as using an 0805 footprint for a resistor).</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="kn">from</span> <span class="nn">.logger</span> <span class="kn">import</span> <span class="n">active_logger</span>

    <span class="n">active_logger</span><span class="o">.</span><span class="n">bare_error</span><span class="p">(</span>
        <span class="sa">f</span><span class="s2">&quot;No footprint for </span><span class="si">{</span><span class="n">part</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">/</span><span class="si">{</span><span class="n">part</span><span class="o">.</span><span class="n">ref</span><span class="si">}</span><span class="s2"> added at </span><span class="si">{</span><span class="n">part</span><span class="o">.</span><span class="n">src_line</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span><span class="si">}</span><span class="s2">.&quot;</span>
    <span class="p">)</span></div>

</pre></div>

            <div class="clearer"></div>
          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="Main">
        <div class="sphinxsidebarwrapper">
<search id="searchbox" style="display: none" role="search">
  <h3 id="searchlabel">Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="../../search.html" method="get">
      <input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
      <input type="submit" value="Go" />
    </form>
    </div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="Related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="nav-item nav-item-0"><a href="../../index.html">SKiDL 2.2.0 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../index.html" >Module code</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">skidl.part</a></li> 
      </ul>
    </div>
    <div class="footer" role="contentinfo">
    &#169; Copyright 2016-2025, Dave Vandenbout.
      Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
    </div>
  </body>
</html>